home *** CD-ROM | disk | FTP | other *** search
/ MacFormat España 15 / macformat_15.iso / Shareware Internet / Ciencia / CFG 2.3 (Shareware) / µCinema Converter / PICS to QuickTime.c < prev    next >
Text File  |  1994-04-10  |  11KB  |  409 lines

  1. /********************************************************************
  2.     µCinema Converter 1.0
  3.     module: PICS to QuickTime.c
  4.     February 1994 - April 1994
  5.     by John A. Schlack
  6.  *********************************************************************************/
  7.  
  8.  
  9. #include <Movies.h>
  10. #include <Script.h>
  11.  
  12. #include "constants.h"
  13. #include "PICS to QuickTime.h"
  14. #include "preferences.h"
  15. #include "pstring.h"
  16. #include "µCinema.h"
  17.  
  18.  
  19. /* --------------------------------------------------------------------------------- */
  20.  
  21.  
  22. #define BASE_PICT_INDEX        128
  23.  
  24.  
  25. /* --------------------------------------------------------------------------------- */
  26.  
  27.  
  28. typedef struct pics_info
  29. {
  30.     short    bwColor;    // 0 = BW, 1 = color
  31.     short    depth;        // bits per pixel
  32.     short    speed;        // frames per second ???
  33.     short    version;    // set to 0
  34.     OSType    creator;
  35.     long    maxFrame;    // maximum frame size
  36. } pics_info;
  37.  
  38.  
  39. /* --------------------------------------------------------------------------------- */
  40.  
  41.  
  42. static pics_info    rPICSInfo;
  43. static short        basePictIndex;
  44.  
  45.  
  46. /* --------------------------------------------------------------------------------- */
  47.  
  48.  
  49. static void     picsToMovie( FSSpec * picsFile, FSSpec * movieFile );
  50. static void     CreateMyVideoTrack( Movie theMovie, FSSpec * spec );
  51. static void     AddVideoSamples( Media theMedia, Rect * trackFrame, long max,
  52.                     unsigned char * picsFileName );
  53. static void     DrawMyFrame( Rect * trackFrame, short id );
  54. static Boolean    inputFileValid( FSSpec * picsFile, Boolean interactive );
  55. static void     buildName( unsigned char * newBaseName, unsigned char * variant );
  56.  
  57.  
  58. /* --------------------------------------------------------------------------------- */
  59.  
  60.  
  61. void picsToMovieBatch( FSSpec * picsFile )
  62. {
  63.     FSSpec    movieFile;
  64.     Str63    tempName;
  65.     long    attempts;
  66.     short    fileRefNo;
  67.     
  68.     if (!inputFileValid( picsFile, false ))
  69.         return;
  70.  
  71.     /* build file name, if file with duplicate name present, try a new name */
  72.  
  73.     movieFile = *picsFile;
  74.     pstrcpy( tempName, movieFile.name );
  75.     buildName( tempName, movieFile.name );
  76.     for (attempts=0L; attempts<1000L; attempts++)
  77.     {
  78.         if (FSpOpenRF( &movieFile, fsRdPerm, &fileRefNo ) != noErr)
  79.             break;
  80.         FSClose( fileRefNo );
  81.         buildName( nil, movieFile.name );
  82.     }
  83.     
  84.     /* abort if failed to find new name after great number of attempts */
  85.     
  86.     if (attempts >= 1000L)
  87.     {
  88.         errorHandlerParameter( ERR_INPUT_FILE, picsFile->name );
  89.         return;
  90.     }
  91.     
  92.     /* convert the file */
  93.     
  94.     picsToMovie( picsFile, &movieFile );
  95. }
  96.  
  97.  
  98. /* --------------------------------------------------------------------------------- */
  99.  
  100.  
  101. void picsToMovieInteractive( void )
  102. {
  103.     Str63                tempName;
  104.     SFTypeList             typelist;
  105.     StandardFileReply    getreply, putreply;
  106.  
  107.     typelist[0] = 'PICS';
  108.     StandardGetFile(nil, 1, typelist, &getreply);
  109.     if (!getreply.sfGood)
  110.         return;
  111.  
  112.     if (!inputFileValid( &getreply.sfFile, true ))
  113.         return;
  114.  
  115.     buildName( getreply.sfFile.name, tempName );
  116.     StandardPutFile("\pSave movie as:", tempName, &putreply);
  117.     if (!putreply.sfGood)
  118.         return;
  119.     
  120.     picsToMovie( &getreply.sfFile, &putreply.sfFile );
  121. }
  122.  
  123.  
  124. /* --------------------------------------------------------------------------------- */
  125.  
  126.  
  127. static void picsToMovie( FSSpec * picsFile, FSSpec * movieFile )
  128. {
  129.     Movie    theMovie = nil;
  130.     OSErr    err = noErr;
  131.     short    saveref, resRefNum = 0, resId = 0;
  132.     
  133.     saveref = CurResFile();
  134.     err = EnterMovies();
  135.  
  136.     err = CreateMovieFile( movieFile, 'SPLY', smCurrentScript, createMovieFileDeleteCurFile,
  137.         &resRefNum, &theMovie );
  138.     CreateMyVideoTrack( theMovie, picsFile );
  139.     err = AddMovieResource( theMovie, resRefNum, &resId, movieFile->name );
  140.     if (resRefNum)
  141.         CloseMovieFile( resRefNum );
  142.  
  143.     UseResFile(saveref);
  144.     ExitMovies();
  145. }
  146.  
  147.  
  148. /* --------------------------------------------------------------------------------- */
  149.  
  150.  
  151. static void CreateMyVideoTrack( Movie theMovie, FSSpec * spec )
  152. {
  153.     Str255        dummyName;
  154.     ResType        dummyType;
  155.     Track        theTrack;
  156.     Media        theMedia;
  157.     OSErr        err = noErr;
  158.     Rect        trackFrame = { 0, 0, 160, 120 };
  159.     Handle        myres;
  160.     short        resfile, max;
  161.     
  162.     resfile = FSpOpenResFile( spec, fsRdPerm );
  163.     if (resfile == -1)
  164.     {
  165.         errorHandlerParameter( ERR_INPUT_FILE, spec->name );
  166.         return;
  167.     }
  168.     UseResFile( resfile );
  169.     
  170.     max = Count1Resources( 'PICT' );
  171.     if (max <= 0)
  172.     {
  173.         errorHandlerParameter( ERR_PICS_DATA, spec->name );
  174.         return;
  175.     }
  176.     
  177.     /*
  178.         Attempt to get first PICT data item.  The default is index 128.  If it is
  179.         not there, get first PICT item.  Abort if item index is less than 128.
  180.     */
  181.     basePictIndex = BASE_PICT_INDEX;
  182.     myres = Get1Resource( 'PICT', basePictIndex );
  183.     if (myres == NULL)
  184.     {
  185.         myres = Get1IndResource( 'PICT', 1 );
  186.         if (myres != NULL)
  187.         {
  188.             GetResInfo( myres, &basePictIndex, &dummyType, dummyName );
  189.             if (basePictIndex < BASE_PICT_INDEX)
  190.             {
  191.                 ReleaseResource( myres );
  192.                 myres = nil;
  193.             }
  194.         }
  195.     }
  196.     
  197.     if (myres == nil)
  198.     {
  199.         errorHandlerParameter( ERR_PICS_DATA, spec->name );
  200.         return;
  201.     }
  202.     LoadResource( myres );
  203.     trackFrame = (**((PicHandle) myres)).picFrame;
  204.     ReleaseResource( myres );
  205.     
  206.     theTrack = NewMovieTrack( theMovie, FixRatio( trackFrame.right, 1 ),
  207.         FixRatio( trackFrame.bottom, 1 ), kNoVolume );
  208.     err = GetMoviesError();
  209.     
  210.     theMedia = NewTrackMedia( theTrack, VideoMediaType, rPICSInfo.speed, NULL, 0 );
  211.     err = GetMoviesError();
  212.     
  213.     err = BeginMediaEdits( theMedia );
  214.     AddVideoSamples( theMedia, &trackFrame, (long) max, spec->name );
  215.     err = EndMediaEdits( theMedia );
  216.     
  217.     err = InsertMediaIntoTrack( theTrack, 0, 0, GetMediaDuration( theMedia ), 0x00010000L );
  218. }
  219.  
  220.  
  221. /* --------------------------------------------------------------------------------- */
  222.  
  223.  
  224. static void AddVideoSamples( Media theMedia, Rect * trackFrame, long max,
  225.     unsigned char * picsFileName )
  226. {
  227.     long        maxCompressedSize;
  228.     GWorldPtr    theGWorld;
  229.     long        curSample;
  230.     Handle        compressedData = nil;
  231.     Ptr            compressedDataPtr;
  232.     ImageDescriptionHandle    imageDesc = nil;
  233.     CGrafPtr    oldPort;
  234.     GDHandle    oldGDeviceH;
  235.     OSErr        err = noErr;
  236.     short        j;
  237.     
  238.     err = NewGWorld( &theGWorld, 8 /* depth */, trackFrame, nil, nil, (GWorldFlags) 0 );
  239.     LockPixels( theGWorld->portPixMap );
  240.     err = GetMaxCompressionSize( theGWorld->portPixMap, trackFrame, 0,
  241.         codecNormalQuality, 'rle ', (CompressorComponent) anyCodec,
  242.         &maxCompressedSize );
  243.         
  244.     compressedData = NewHandle( maxCompressedSize );
  245.     if (MemError())
  246.     {
  247.         errorHandlerParameter( ERR_MEMORY, picsFileName );
  248.         return;
  249.     }
  250.     MoveHHi( compressedData );
  251.     HLock( compressedData );
  252.     compressedDataPtr = StripAddress( *compressedData );
  253.     
  254.     imageDesc = (ImageDescriptionHandle) NewHandle( 4L );
  255.     if (MemError())
  256.     {
  257.         errorHandlerParameter( ERR_MEMORY, picsFileName );
  258.         return;
  259.     }
  260.     
  261.     GetGWorld( &oldPort, &oldGDeviceH );
  262.     SetGWorld( theGWorld, nil );
  263.     
  264.     for (curSample=0L, j=basePictIndex; curSample<max; curSample++, j++)
  265.     {
  266.         EraseRect( trackFrame );
  267.         DrawMyFrame( trackFrame, j );
  268.         
  269.         err = CompressImage( theGWorld->portPixMap, trackFrame, codecNormalQuality,
  270.             'rle ', imageDesc, compressedDataPtr );
  271.         err = AddMediaSample( theMedia, compressedData, 0, (**imageDesc).dataSize,
  272.             1, (SampleDescriptionHandle) imageDesc, 1, 0, nil );
  273.     }
  274.     
  275.     SetGWorld( oldPort, oldGDeviceH );
  276.     if (imageDesc != NULL)
  277.         DisposeHandle( (Handle) imageDesc );
  278.     if (compressedData != NULL)
  279.         DisposeHandle( compressedData );
  280.     if (theGWorld != NULL)
  281.         DisposeGWorld( theGWorld );
  282. }
  283.  
  284.  
  285. /* --------------------------------------------------------------------------------- */
  286.  
  287.  
  288. static void DrawMyFrame( Rect * trackFrame, short id )
  289. {
  290.     Handle    pict;
  291.     
  292.     pict = Get1Resource( 'PICT', id );
  293.     if (pict == nil)
  294.         return;
  295.     LoadResource( pict );
  296.     DrawPicture( (PicHandle) pict, trackFrame );
  297.     ReleaseResource( pict );
  298. }
  299.  
  300.  
  301. /* --------------------------------------------------------------------------------- */
  302.  
  303.  
  304. static Boolean inputFileValid( FSSpec * picsFile, Boolean interactive )
  305. /*
  306.     Checks to see that the file if of type 'PICS'.  Also, checks loads the PICS info
  307.     resource.  If not found, dialog displayed if interactive, else, preferences
  308.     value is used.
  309. */
  310. {
  311.     FInfo    info;
  312.     Handle    picsInfo;
  313.     short    saveref, resfile;
  314.     Boolean    infoValid = false;
  315.     
  316.     if (FSpGetFInfo( picsFile, &info) != noErr)
  317.     {
  318.         errorHandlerParameter( ERR_INPUT_FILE, picsFile->name );
  319.         return false;
  320.     }
  321.     if (info.fdType != 'PICS')
  322.     {
  323.         errorHandlerParameter( ERR_NOT_PICS, picsFile->name );
  324.         return false;
  325.     }
  326.  
  327.     saveref = CurResFile();
  328.     resfile = FSpOpenResFile( picsFile, fsRdPerm );
  329.     if (resfile == -1)
  330.     {
  331.         errorHandlerParameter( ERR_INPUT_FILE, picsFile->name );
  332.         return false;
  333.     }
  334.     picsInfo = Get1Resource( 'INFO', 128 );
  335.     if (picsInfo != nil)
  336.     {
  337.         if (SizeResource( picsInfo ) == sizeof( pics_info ))
  338.         {
  339.             LoadResource( picsInfo );
  340.             HLock( picsInfo );
  341.             BlockMove( *picsInfo, &rPICSInfo, sizeof( rPICSInfo ) );
  342.             HUnlock( picsInfo );
  343.             ReleaseResource( picsInfo );
  344.             if ((rPICSInfo.speed >= 1) && (rPICSInfo.speed <= 60))
  345.                 infoValid = true;
  346.         }
  347.     }
  348.     UseResFile(saveref);
  349.     CloseResFile( resfile );
  350.     
  351.     if (!infoValid)
  352.     {
  353.         if (!interactive)
  354.             rPICSInfo.speed = copyPrefsFPS();
  355.         else if (!preferencesDialog( &rPICSInfo.speed ))
  356.             return false;    /* user canceled, so abort */
  357.     }
  358.     return true;
  359. }
  360.  
  361.  
  362. /* --------------------------------------------------------------------------------- */
  363.  
  364.  
  365. static void buildName( unsigned char * newBaseName, unsigned char * variant )
  366. {
  367.     static Str63    base = "\p";        /* stores file name last used */
  368.     static long        nextNum = 1L;        /* stores integer number for appending non-unique name */
  369.     static short    insertPoint = 1;    /* stores location to start inserting number */
  370.     
  371.     unsigned char    numText[12];        /* provide enough storage for largest possible long converted to string */
  372.     short            len;
  373.     
  374.     if (newBaseName != nil)
  375.     {
  376.         /* make a copy of the new base name */
  377.         pstrcpy( base, newBaseName );
  378.         len = (short) base[0];
  379.         
  380.         /* if name ends in ".PICS", insert new extension at the '.' */
  381.         insertPoint = (!memcmpi( base+len-4, ".PICS", 5L )) ? (len-4) : (len+1);
  382.         
  383.         /* max file name is 31 chars, need 3 chars for ".QT" extension */
  384.         if (insertPoint > 29)
  385.             insertPoint = 29;
  386.         base[insertPoint] = '.';
  387.         base[++insertPoint] = 'Q';
  388.         base[++insertPoint] = 'T';
  389.         base[0] = insertPoint++;    /* set length of P string, inc insert point so intserting after the 'T' */
  390.         nextNum = 1L;
  391.     }
  392.     else
  393.     {
  394.         NumToString( nextNum++, numText );
  395.         if ((insertPoint + numText[0]) > 32)    /* 32 is proper number, even though max len is 31 */
  396.         {
  397.             insertPoint -= ((insertPoint + numText[0]) - 32);
  398.             base[insertPoint-3] = '.';
  399.             base[insertPoint-2] = 'Q';
  400.             base[insertPoint-1] = 'T';
  401.         }
  402.         BlockMove( numText+1, base+insertPoint, (long) numText[0] );
  403.         base[0] = insertPoint + numText[0] - 1;
  404.     }
  405.         
  406.     /* copy new file name to output buffer */
  407.     pstrcpy( variant, base );
  408. }
  409.